package com.managertrade.service.sqllite.impl;

import com.managertrade.dao.sqlite.entity.KlineWithIndicatorsEntity;
import com.managertrade.dao.sqlite.repository.KlineWithIndicatorsRepository;
import com.managertrade.dto.vo.KlineWithIndicators;
import com.managertrade.service.sqllite.service.KlineWithIndicatorsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class KlineWithIndicatorsServiceImpl implements KlineWithIndicatorsService {

    private final KlineWithIndicatorsRepository repository;

    public KlineWithIndicatorsServiceImpl(KlineWithIndicatorsRepository repository) {
        this.repository = repository;
    }

    @Override
    public KlineWithIndicatorsEntity save(KlineWithIndicatorsEntity kline) {
        // 自动生成 uniqueId 和 datetime
        kline.setUniqueId(generateUniqueId(kline));
        kline.setDatetime(formatTimestamp(kline.getTimestamp()));
        return repository.save(kline);
    }

    @Override
    public List<KlineWithIndicatorsEntity> saveAll(List<KlineWithIndicatorsEntity> klines) {
        klines.forEach(k -> {
            k.setUniqueId(generateUniqueId(k));
            k.setDatetime(formatTimestamp(k.getTimestamp()));
        });
        return repository.saveAll(klines);
    }

    @Override
    public Optional<KlineWithIndicatorsEntity> findById(String uniqueId) {
        return repository.findById(uniqueId);
    }

    @Override
    public List<KlineWithIndicatorsEntity> findAll() {
        return repository.findAll();
    }

    @Override
    public void deleteById(String uniqueId) {
        repository.deleteById(uniqueId);
    }

    @Override
    public KlineWithIndicatorsEntity updateById(String uniqueId, KlineWithIndicatorsEntity kline) {
        Optional<KlineWithIndicatorsEntity> optional = repository.findById(uniqueId);
        if (optional.isPresent()) {
            KlineWithIndicatorsEntity entity = optional.get();
            // 更新字段
            entity.setOpen(kline.getOpen());
            entity.setHigh(kline.getHigh());
            entity.setLow(kline.getLow());
            entity.setClose(kline.getClose());
            entity.setVolume(kline.getVolume());
            entity.setEma7(kline.getEma7());
            entity.setEma21(kline.getEma21());
            entity.setMacd(kline.getMacd());
            entity.setSignal(kline.getSignal());
            entity.setHistogram(kline.getHistogram());
            entity.setBollUpper(kline.getBollUpper());
            entity.setBollMiddle(kline.getBollMiddle());
            entity.setBollLower(kline.getBollLower());
            entity.setSymbol(kline.getSymbol());
            entity.setPeriod(kline.getPeriod());
            entity.setMacdDiff(kline.getMacdDiff());
            entity.setMacdDea(kline.getMacdDea());
            entity.setMacdBar(kline.getMacdBar());
            // 更新 uniqueId 和 datetime
            entity.setUniqueId(generateUniqueId(entity));
            entity.setDatetime(formatTimestamp(entity.getTimestamp()));
            return repository.save(entity);
        } else {
            throw new RuntimeException("Kline 数据不存在: " + uniqueId);
        }
    }

    @Override
    public void saveIfNotExists(List<KlineWithIndicators> klineList) {
        if (klineList == null || klineList.isEmpty()) return;

        // 取出所有 uniqueId
        List<String> uniqueIds = klineList.stream()
                .map(KlineWithIndicators::getUniqueId)
                .collect(Collectors.toList());

        // 查数据库中已存在的 uniqueId
        List<String> existIds = repository.findAllByUniqueIdIn(uniqueIds)
                .stream()
                .map(KlineWithIndicatorsEntity::getUniqueId)
                .collect(Collectors.toList());

        // 筛选出不存在的 kline
        List<KlineWithIndicatorsEntity> toSave = klineList.stream()
                .filter(k -> !existIds.contains(k.getUniqueId()))
                .map(this::convertToEntity)
                .collect(Collectors.toList());

        // 批量保存
        if (!toSave.isEmpty()) {
            log.info("更新数据到 sqlite 条数：{} ",toSave.size());
            repository.saveAll(toSave);
        }
    }

    @Override
    public KlineWithIndicatorsEntity findTopBySymbolAndPeriodOrderByTimestampDesc(String symbol, String period) {
        return repository.findTopBySymbolAndPeriodOrderByTimestampDesc(symbol,period);
    }

    @Override
    public List<KlineWithIndicatorsEntity> findBySymbolAndPeriodPaged(String symbol, String period, Pageable pageable) {
        return repository.findBySymbolAndPeriod(symbol ,period ,pageable);
    }

    @Override
    public List<KlineWithIndicatorsEntity> findLatestBySymbolAndPeriod(String symbol, String period) {
         return repository.findLatestBySymbolAndPeriod( symbol, period,100 );
    }


    private KlineWithIndicatorsEntity convertToEntity(KlineWithIndicators kline) {
        KlineWithIndicatorsEntity entity = new KlineWithIndicatorsEntity();
        entity.setUniqueId(kline.getUniqueId());
        entity.setTimestamp(kline.getTimestamp());
        entity.setDatetime(kline.getDatetime());
        entity.setSymbol(kline.getSymbol());
        entity.setPeriod(kline.getPeriod());
        entity.setOpen(kline.getOpen());
        entity.setHigh(kline.getHigh());
        entity.setLow(kline.getLow());
        entity.setClose(kline.getClose());
        entity.setVolume(kline.getVolume());
        entity.setEma7(kline.getEma7());
        entity.setEma21(kline.getEma21());
        entity.setMacd(kline.getMacd());
        entity.setSignal(kline.getSignal());
        entity.setHistogram(kline.getHistogram());
        entity.setBollUpper(kline.getBollUpper());
        entity.setBollMiddle(kline.getBollMiddle());
        entity.setBollLower(kline.getBollLower());
        entity.setMacdDiff(kline.getMacdDiff());
        entity.setMacdDea(kline.getMacdDea());
        entity.setMacdBar(kline.getMacdBar());
        return entity;
    }
    private String generateUniqueId(KlineWithIndicatorsEntity k) {
        return k.getSymbol() + "_" + k.getPeriod() + "_" + k.getTimestamp();
    }

    private String formatTimestamp(long timestamp) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
    }
}
